<!DOCTYPE html>
<html lang="en">

<head>
    <title></title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <audio autoplay id="audio"></audio>
    <canvas id='canvas' width="800" height="350"></canvas>
</body>
<script>
    _drawSpectrum = function (analyser) {
        var that = this,
            canvas = document.getElementById('canvas'),
            cwidth = canvas.width,
            cheight = canvas.height - 2,
            meterWidth = 10, //width of the meters in the spectrum // 单位长度
            gap = 2, //gap between meters // 间隔
            capHeight = 2,
            capStyle = '#fff',
            meterNum = 800 / (10 + 2), //count of the meters // 能量槽数目
            capYPositionArray = []; ////store the vertical position of hte caps for the preivous frame
        ctx = canvas.getContext('2d'),
            gradient = ctx.createLinearGradient(0, 0, 0, 300); //线性渐变
        gradient.addColorStop(1, '#0f0');
        gradient.addColorStop(0.5, '#ff0');
        gradient.addColorStop(0, '#f00');
        var drawMeter = function () {
            var array = new Uint8Array(analyser.frequencyBinCount); // array长度和frequencyBinCount长度相等
            analyser.getByteFrequencyData(array); // 将当前的频率数据传入array
            console.log(array);
            console.log(analyser.frequencyBinCount);
            var step = Math.round(array.length / meterNum); //sample limited data from the total array
            ctx.clearRect(0, 0, cwidth, cheight);
            for (var i = 0; i < meterNum; i++) {
                var value = array[i * step];
                if (capYPositionArray.length < Math.round(meterNum)) {
                    capYPositionArray.push(value);
                }
                ;
                ctx.fillStyle = capStyle;
                //draw the cap, with transition effect
                if (value < capYPositionArray[i]) {
                    ctx.fillRect(i * 12, cheight - (--capYPositionArray[i]), meterWidth, capHeight);
                } else {
                    ctx.fillRect(i * 12, cheight - value, meterWidth, capHeight);
                    capYPositionArray[i] = value;
                }
                ;
                ctx.fillStyle = gradient; //set the filllStyle to gradient for a better look
                ctx.fillRect(i * 12 /*meterWidth+gap*/, cheight - value + capHeight, meterWidth, cheight); //the meter
            }
            requestAnimationFrame(drawMeter) // 递归调用
        }
        requestAnimationFrame(drawMeter);
    }


    let constraints = { audio: true, video: false };

    navigator.mediaDevices.getUserMedia(constraints)
        .then(function (stream) {
            // for play
            let audio = document.getElementById('audio')
            audio.srcObject = stream
            let audioCtx = new AudioContext();
            let source = audioCtx.createMediaStreamSource(stream);
            let analyser = audioCtx.createAnalyser()
            source.connect(analyser)
            console.log(analyser)
            analyser.fftSize = 1024
            _drawSpectrum(analyser)        
        })
        .catch(function (err) { console.log(err.name + ": " + err.message); });

</script>

</html>